package com.punai.customer.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.punai.common.utils.SecurityUtils;
import com.punai.common.utils.StringUtils;
import com.punai.customer.domain.CusLinkFeature;
import com.punai.customer.domain.CusMechanicalChapter;
import com.punai.customer.domain.CusMechanicalItem;
import com.punai.customer.domain.bo.CusLinkFeatureBo;
import com.punai.customer.domain.bo.CusMechanicalItemBo;
import com.punai.customer.domain.contants.CusConstants;
import com.punai.customer.domain.request.CusMechanicalItemRequest;
import com.punai.customer.domain.request.CusRewriteCodeRequest;
import com.punai.customer.domain.vo.CusLinkStaVo;
import com.punai.customer.mapper.*;
import com.punai.customer.service.ICusMechanicalItemService;
import com.punai.gk.domain.vo.SimplifyVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 机械费用项Service业务层处理
 *
 * @author ruoyi
 * @date 2022-12-04
 */
@Service
public class CusMechanicalItemServiceImpl extends ServiceImpl<CusMechanicalItemMapper,CusMechanicalItem> implements ICusMechanicalItemService
{
    @Autowired
    private CusMechanicalItemMapper cusMechanicalItemMapper;
    @Autowired
    private CusMechanicalChapterMapper cusMechanicalChapterMapper;
    @Autowired
    private CusMechanicalStaItemMapper cusMechanicalStaItemMapper;
    @Autowired
    private CusLinkFeatureMapper cusLinkFeatureMapper;
    @Autowired
    private CusLinkMechanicalStaCusMapper staCusMapper;

    /**
     * 查询机械费用项
     *
     * @param id 机械费用项主键
     * @return 机械费用项
     */
    @Override
    public CusMechanicalItemBo selectCusMechanicalItemById(String id, Long companyId)
    {
        CusMechanicalItemBo cusMechanicalItemBo = new CusMechanicalItemBo();
        cusMechanicalItemBo.setCusMechanicalItem(cusMechanicalItemMapper.selectCusMechanicalItemById(id,companyId));
        cusMechanicalItemBo.setCusLinkStaVoList(cusMechanicalStaItemMapper.selectByCusId(id, companyId));
        List<String> ids = new ArrayList<>(1);
        ids.add(id);
        // 关联特征
        List<CusLinkFeatureBo> cusLinkFeatureBos = cusLinkFeatureMapper.selectLinkFeatureByItemIds(companyId, ids);
        for (CusLinkFeatureBo cusLinkFeatureBo : cusLinkFeatureBos) {
            cusLinkFeatureBo.setItemNames(CollUtil.toList(cusLinkFeatureBo.getFeatureValues().split("\\|")));
        }
        cusMechanicalItemBo.setCusLinkFeatureList(cusLinkFeatureBos);
        return cusMechanicalItemBo;
    }

    /**
     * 查询机械费用项列表
     *
     * @param cusMechanicalItem 机械费用项
     * @return 机械费用项
     */
    @Override
    public List<CusMechanicalItem> selectCusMechanicalItemList(CusMechanicalItem cusMechanicalItem) {
        Long companyId = cusMechanicalItem.getCompanyId();
        List<CusMechanicalItem> cusMechanicalItems = cusMechanicalItemMapper.selectCusMechanicalItemList(cusMechanicalItem);
        if(CollUtil.isNotEmpty(cusMechanicalItems)){
            List<String> ids = cusMechanicalItems.stream().map(CusMechanicalItem::getId).collect(Collectors.toList());
            List<SimplifyVo> simplifyVos = cusLinkFeatureMapper.selectLinkFeature(companyId, ids);
            Map<String, String> linkFeatureMap = simplifyVos.stream().collect(Collectors.toMap(SimplifyVo::getId, SimplifyVo::getName));
            cusMechanicalItems.forEach(e -> e.setLinkFeatures(linkFeatureMap.get(e.getId())));
        }
        return cusMechanicalItems;
    }

    @Override
    @Transactional
    public int insertCusMechanicalItem(CusMechanicalItemRequest cusMechanicalItemRequest)
    {
        Long companyId = SecurityUtils.getCompanyId();
        CusMechanicalItem cusMechanicalItem = cusMechanicalItemRequest.getCusMechanicalItem();
        if(StringUtils.isEmpty(cusMechanicalItem.getChapterId())){
            throw new RuntimeException("未选择章节");
        }
        if(StringUtils.isEmpty(cusMechanicalItem.getItemName())){
            throw new RuntimeException("未输入名称");
        }
        if(StringUtils.isEmpty(cusMechanicalItem.getUnit())){
            throw new RuntimeException("未输入单位");
        }
        cusMechanicalItem.setCompanyId(companyId);
        CusMechanicalChapter cusMechanicalChapter = cusMechanicalChapterMapper.selectCusMechanicalChapterById(cusMechanicalItem.getChapterId(), companyId);
        if(cusMechanicalChapter == null){
            throw new RuntimeException("章节不存在");
        }
        if (cusMechanicalItem.getOrderNum() == null) {
            Integer maxOrderNum = getMaxOrderNum(companyId,cusMechanicalItem.getChapterId());
            cusMechanicalItem.setOrderNum(maxOrderNum + 1);
        }
        int insertMsg = cusMechanicalItemMapper.insert(cusMechanicalItem);
        if(insertMsg > 0){
            List<CusLinkFeature> cusLinkFeatureList = cusMechanicalItemRequest.getCusLinkFeatureList();
            if(CollUtil.isNotEmpty(cusLinkFeatureList)){
                for (CusLinkFeature cusLinkFeature : cusLinkFeatureList) {
                    cusLinkFeature.setCompanyId(companyId);
                    cusLinkFeature.setItemId(cusMechanicalItem.getId());
                }
                cusLinkFeatureMapper.insertBatchSomeColumn(cusLinkFeatureList);
            }
        }else {
            throw new RuntimeException("新增失败");
        }
        return 200;
    }

    private Integer getMaxOrderNum(Long companyId, String chapterId) {
        return cusMechanicalItemMapper.selectMaxOrderNum(companyId,chapterId);
    }

    @Override
    @Transactional
    public int updateCusMechanicalItem(CusMechanicalItemRequest cusMechanicalItemRequest)
    {
        Long companyId = SecurityUtils.getCompanyId();
        CusMechanicalItem cusMechanicalItem = cusMechanicalItemRequest.getCusMechanicalItem();
        List<CusLinkStaVo> cusLinkStaVoList = cusMechanicalItemRequest.getCusLinkStaVoList();
        List<CusLinkFeature> cusLinkFeatureList = cusMechanicalItemRequest.getCusLinkFeatureList();
        String cusId = cusMechanicalItem.getId();

        // 处理换算系数
        List<String> linkStaIds = cusLinkStaVoList.stream().map(CusLinkStaVo::getId).collect(Collectors.toList());
        staCusMapper.deleteByNotInId(companyId,cusId,linkStaIds);
        if(CollUtil.isNotEmpty(cusLinkStaVoList)){
            for (CusLinkStaVo cusLinkStaVo : cusLinkStaVoList) {
                staCusMapper.updateCoefficient(companyId,cusLinkStaVo);
            }
        }

        // 处理关联特征
        List<String> ids = new ArrayList<>(1);
        ids.add(cusId);
        cusLinkFeatureMapper.deleteByItemIds(companyId,ids);

        if(CollUtil.isNotEmpty(cusLinkFeatureList)){
            for (CusLinkFeature cusLinkFeature : cusLinkFeatureList) {
                cusLinkFeature.setCompanyId(companyId);
                cusLinkFeature.setItemId(cusMechanicalItem.getId());
            }
            cusLinkFeatureMapper.insertBatchSomeColumn(cusLinkFeatureList);
        }

        LambdaQueryWrapper<CusMechanicalItem> wrapper = Wrappers.<CusMechanicalItem>lambdaQuery()
                .eq(CusMechanicalItem::getId, cusMechanicalItem.getId())
                .eq(CusMechanicalItem::getCompanyId, cusMechanicalItem.getCompanyId());
        cusMechanicalItemMapper.update(cusMechanicalItem,wrapper);
        return 200;
    }

    /**
     * 批量删除机械费用项
     *
     * @param ids 需要删除的机械费用项主键
     * @return 结果
     */
    @Override
    @Transactional
    public int deleteCusMechanicalItemByIds(List<String> ids,Long companyId)
    {
        // 删除关联
        staCusMapper.deleteByCusIds(companyId, ids);
        return cusMechanicalItemMapper.deleteCusMechanicalItemByIds(ids,companyId);
    }

    @Override
    @Transactional
    public int setConsumptionVal(String id, BigDecimal consumption, Long companyId) {
        return cusMechanicalItemMapper.setConsumptionVal(id,companyId, consumption);
    }

    @Override
    @Transactional
    public int moveToChapter(String[] ids, String chapterId, Long companyId) {
        // 移动章节
        cusMechanicalItemMapper.updateChapterIdByIds(ids,chapterId,companyId);
        return 1;
    }

    @Override
    public Long countChapterIdIsZero(Long companyId) {
        return cusMechanicalItemMapper.selectCount(new LambdaQueryWrapper<CusMechanicalItem>().eq(CusMechanicalItem::getCompanyId,companyId).eq(CusMechanicalItem::getChapterId, CusConstants.CHAPTER_ID_NULL));
    }

    @Override
    @Transactional
    public int rewriteCode(CusRewriteCodeRequest codeRequest) {
        Long companyId = SecurityUtils.getCompanyId();
        int countNotAllot = cusMechanicalItemMapper.countNotAllot(companyId, CusConstants.CHAPTER_ID_NULL);
        if (countNotAllot != 0) {
            throw new RuntimeException("存在未分配章节的费用项");
        }
        Integer suffixLen = codeRequest.getSuffixLen();
        Integer maxCountLen = cusMechanicalItemMapper.countByChapterId(companyId);
        if(suffixLen < maxCountLen){
            throw new RuntimeException("根据费用项数量统计,编码后缀不能少于" + maxCountLen + "位");
        }
        cusMechanicalItemMapper.rewriteMechanicalCode(companyId,codeRequest.getPrefix(),suffixLen);
        return 1;
    }

    @Override
    public List<CusMechanicalItem> validateCode(Long companyId) {
        int countNotAllot = cusMechanicalItemMapper.countNotAllot(companyId, CusConstants.CHAPTER_ID_NULL);
        if (countNotAllot != 0) {
            throw new RuntimeException("存在未分配章节的费用项");
        }
        List<CusMechanicalItem> cusMechanicalItems = new ArrayList<>();
        LambdaQueryWrapper<CusMechanicalItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CusMechanicalItem::getCompanyId, companyId);
        wrapper.groupBy(CusMechanicalItem::getCode);
        wrapper.having("count(*) > 1 or `code`='' or ISNULL(`code`)");
        cusMechanicalItems = cusMechanicalItemMapper.selectList(wrapper);
        return cusMechanicalItems;
    }

}
